import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 35326
 * 2021/3/28 16:15
 */
public class CommonTest1 {
	public static void main(String[] args) throws InterruptedException {
		FooBar fooBar = new FooBar(2);
		fooBar.foo(()->{
			System.out.println("foo");
		});
		fooBar.bar(()->{
			System.out.println("bar");
		});

	}
}

class Foo {
	Semaphore semaphore = new Semaphore(0);
	Semaphore semaphore1 = new Semaphore(0);
	ArrayBlockingQueue<String> arrayBlockingQueue12 = new ArrayBlockingQueue<>(1);
	ArrayBlockingQueue<String> arrayBlockingQueue23 = new ArrayBlockingQueue<>(1);
	public Foo() {

	}

	public void first(Runnable printFirst) throws InterruptedException {

		arrayBlockingQueue12.put("stop");




		// printFirst.run() outputs "first". Do not change or remove this line.
		printFirst.run();


	}

	public void second(Runnable printSecond) throws InterruptedException {
			arrayBlockingQueue12.take();
			// printSecond.run() outputs "second". Do not change or remove this line.
			printSecond.run();
			arrayBlockingQueue23.put("Stop");

	}

	public void third(Runnable printThird) throws InterruptedException {
			arrayBlockingQueue23.take();

			// printThird.run() outputs "third". Do not change or remove this line.
			printThird.run();


	}
}

class FooBar {
	private int n;
	volatile int j=0;
	Lock lock = new ReentrantLock();
	Condition notFull = lock.newCondition();
	Condition notEmpty = lock.newCondition();
	public FooBar(int n) {
		this.n = n;
	}

	public void foo(Runnable printFoo) throws InterruptedException {

		for (int i = 0; i < n; i++) {
			lock.lock();
			try{
				if(j==0){
					// printFoo.run() outputs "foo". Do not change or remove this line.
					printFoo.run();
					j++;
					notEmpty.signal();
					Thread.yield();
				}else{
					notFull.await();
				}
			}catch(InterruptedException e){

			}
			finally{
				lock.unlock();
			}



		}
	}

	public void bar(Runnable printBar) throws InterruptedException {

		for (int i = 0; i < n; i++) {

			lock.lock();
			try{
				if(j==1){
					// printBar.run() outputs "bar". Do not change or remove this line.
					printBar.run();
					j--;
					notFull.signal();
					Thread.yield();
				}else{
					notEmpty.await();
				}
			}

			catch(InterruptedException e){

			}
			finally{
				lock.unlock();
			}
		}
	}
}